package com.wangwenjun.concurrency.chapter14.future;


import org.junit.Test;

import java.util.Random;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @Package: com.wangwenjun.concurrency.chapter14.future
 * @ClassName: UseFuture2
 * @Author: lujieni
 * @Description: 2
 * @Date: 2021-03-16 10:44
 * @Version: 1.0
 */
public class UseFuture2 {

    public static void main(String[] args) throws Exception {
        //handle();
        thenApply();
    }
    
    /**
     * @Description: handle 是在任务完成后再执行，还可以处理异常的任务。thenApply 只可以执行正常的任务，任务出现异常则不执行 thenApply 方法。
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    public static void handle() throws Exception{
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
            @Override
            public Integer get() {
                int i= 10/0;
                return new Random().nextInt(10);
            }
        }).handle(new BiFunction<Integer, Throwable, Integer>() {
            @Override
            public Integer apply(Integer param, Throwable throwable) {
                int result = -1;
                if(throwable == null){
                    result = param * 2;
                }else{
                    System.out.println(throwable.getMessage());
                }
                return result;
            }
        });
        System.out.println(future.get());
    }

    /**
     * @Description: 当一个线程依赖另一个线程时，可以使用 thenApply 方法来把这两个线程串行化
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    private static void thenApply(){
        CompletableFuture<Long> future = CompletableFuture.supplyAsync(new Supplier() {
            @Override
            public Long get() {
                System.out.println(Thread.currentThread().getName());
                long result = new Random().nextInt(100);
                System.out.println("result1="+result);
                return result;
            }
        }).thenApplyAsync(new Function<Long, Long>() {
            @Override
            public Long apply(Long t) {
                System.out.println("then apply:"+Thread.currentThread().getName());
                long result = t * 5;
                System.out.println("result2="+result);
                return result;
            }
        });

        long result = 0;
        try {
            result = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(result);
    }

    /**
     * @Description: exceptionally异常会回调 whenComplete异常和正常都会回调
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    public static void whenComplete() throws Exception {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
            if(new Random().nextInt()%2>=0) {
                int i = 12/0;
            }
            System.out.println("run end ...");
        });

        /*
            方法异常和不异常都会回调
         */
        future.whenComplete(new BiConsumer<Void, Throwable>() {
            @Override
            public void accept(Void t, Throwable action) {
                System.out.println("执行完成！");
            }

        });

        /*
            方法抛异常会回调
         */
        future.exceptionally(new Function<Throwable, Void>() {
            @Override
            public Void apply(Throwable t) {
                System.out.println("执行失败！"+t.getMessage());
                return null;
            }
        });

        TimeUnit.SECONDS.sleep(2);
    }

    /**
     * @Description: 使用runAsync
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    @Test
    public void test01(){
        CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
            /*
                交给线程池去执行,默认使用的是forkjoinpool.commonpool,里面的线程都是守护线程
             */
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " runAsync=>Void");
        });

        System.out.println("11111");
        try {
            completableFuture.get();//会阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description: 如果CompletableFuture执行完成的话,whenComplete执行的线程就是主线程
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    @Test
    public  void test02(){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " supplyAsync=>Integer");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        });

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        completableFuture.whenComplete((t,u)->{ //t:正常返回结果 u:可能出现的异常
            System.out.println(Thread.currentThread().getName());//这里竟然是main
            System.out.println("t: "+t);
            System.out.println("u: "+u);
        });

    }


    /**
     * @Description: 如果CompletableFuture执行完成的话,whenComplete执行的线程就是主线程
     * @param
     * @return:
     * @Author: lujieni
     * @Date: 2021/3/16
     */
    @Test
    public void test03(){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " supplyAsync=>Integer");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        }, Executors.newFixedThreadPool(1));


        completableFuture.whenComplete((t,u)->{ //t:正常返回结果 u:可能出现的异常
            System.out.println(Thread.currentThread().getName());//这里竟然是main
            System.out.println("t: "+t);
            System.out.println("u: "+u);
        });

    }

    @Test
    public void test04(){
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + " supplyAsync=>Integer");//pool-1-thread-1 supplyAsync=>Integer
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1024;
        }, Executors.newFixedThreadPool(1));


        completableFuture.whenComplete((t,u)->{
            System.out.println(Thread.currentThread().getName());//pool-1-thread-1
            System.out.println("t: "+t);
            System.out.println("u: "+u);
        });

    }


}